#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>

static int irq; //中断号变量
static char* devname; //注册中断的设备名
static struct tasklet_struct mytasklet; //声明tasklet结构体

module_param(irq,int,0644);//用户向内核传递irq参数
module_param(devname,charp,0644);//用户向内核传递devname参数

struct myirq
{
	int devid;
};
struct myirq mydev={1900};
/* tasklet结构体的处理函数*/
static void mytasklet_handler(unsigned long data)
{
	printk("tasklet is wroking..\n");
}
/*中断处理函数*/
static irqreturn_t myirq_handler(int irq,void* dev)
{
	printk(KERN_ALERT "my irq handler\n");
	struct myirq mydev;
	static int count=0;
	mydev=*(struct myirq*)dev;
	printk("key:%d..\n",count+1);
	printk("devid:%d ISR is working..\n",mydev.devid);
	printk("Bottom half will be working..\n");
	tasklet_init(&mytasklet,mytasklet_handler,0);//动态初始化tasklet
	tasklet_schedule(&mytasklet);//调度tasklet，在tasklet被调度以后，只要有机会它就会尽可能早地运行。
	printk("ISR is leaving..\n");
	count++;
	return IRQ_HANDLED;
}

static int __init myirq_init(void)
{
	int req_ret;
	printk("Module is working..\n");
        req_ret=request_irq(irq,myirq_handler,IRQF_SHARED,devname,&mydev);//以共享中断引脚线的方式注册中断号irq与中断设备devname，中断处理函数为myirq_handler
	printk(KERN_ALERT "req_ret is %d\n",req_ret);
	if(req_ret!=0)
	{
		printk("%s request IRQ:%d failed..\n",devname,irq);
		return -1;
	}
	else printk("%s rquest IRQ:%d success..\n",devname,irq);
	return 0;
}

static void __exit myirq_exit(void)
{
	printk("Module is leaving..\n");
	free_irq(irq,&mydev);
	printk("%s request IRQ:%d success..\n",devname,irq);
}



module_init(myirq_init);
module_exit(myirq_exit);
MODULE_LICENSE("GPL");
